package org.dyndns.opendemogroup.optimizer.operations;

import java.util.Random;

import org.dyndns.opendemogroup.optimizer.IOperation;
import org.dyndns.opendemogroup.optimizer.IOptimizationProblem;
import org.dyndns.opendemogroup.optimizer.Member;
import org.dyndns.opendemogroup.optimizer.Pair;

/**
 * A class to abstract out the commonalities between the IOperation
 * implementations that preserve [some] ordering.
 */
public abstract class OrderPreservingOperationBase implements IOperation
{
	static Pair<Integer, Integer> pickPoints ( Random randomSource,
			final int memberSize )
	{
		final int randomRange = memberSize;
		int pointA = randomSource.nextInt ( randomRange );
		int pointB = randomSource.nextInt ( randomRange );
		// { check that A and B are fine, otherwise fix them
		if ( pointA > pointB )
		{
			int theMysteriousPointC = pointB;
			pointB = pointA;
			pointA = theMysteriousPointC;
		}
		if ( pointA == pointB )
		{
			if ( pointA < memberSize / 2 )
			{
				pointB += 2;
			}
			else
			{
				pointA -= 2;
			}
		}
		// }
		Pair<Integer, Integer> points = new Pair<Integer, Integer> ( );
		points.first = pointA;
		points.second = pointB;
		return points;
	}

	/**
	 * @see IOperation#perform(java.util.Random, IOptimizationProblem, Member,
	 *      Member, Member, Member)
	 */
	public void perform ( Random randomSource, IOptimizationProblem problem,
			Member parentOne, Member parentTwo, Member childOne, Member childTwo )
	{
		final int memberSize = parentOne.getMemberSize ( );
		Pair<Integer, Integer> points = pickPoints ( randomSource, memberSize );

		final int a = points.first, b = points.second;
		perform ( parentOne, parentTwo, childOne, a, b );
		perform ( parentTwo, parentOne, childTwo, a, b );
	}

	abstract void perform ( Member parentOne, Member parentTwo, Member child,
			int a, int b );

}